using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Collections;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Threading;
using System.Runtime.Serialization.Formatters;

using MULENetworking;

namespace MainGame
{
    public partial class ChatRoomGUI : Form
    {
        private string tcpServerAddress = "tcp://localhost:9887/MULEServer";
        private int tcpServerPort = 0;  //9887;
        private string connectAddress;
        private IRemoteServer remoteServer;
        private string myUserName = "null and void";
        private Thread thread;
        private ArrayList userList;
        private ArrayList gamesList;
        string strSessionText = "";
        private bool haveConnectedBefore = false;
        private bool kickMe = false;

        private string gameName;
        //private event FormClosingEventHandler FormClosing;

        private void InitializeRemotingWithServer()
        {
            remoteServer =
               (IRemoteServer)Activator.GetObject(typeof(IRemoteServer), connectAddress);
            //RemotingConfiguration.RegisterWellKnownClientType(typeof(IRemoteServer), connectAddress);
            //if this fails we should focus on tcpServerAddress
            haveConnectedBefore = true;
        }

        public ChatRoomGUI()
        {
            InitializeComponent();
            //this.FormClosing += new FormClosingEventHandler(Form_Closing);
            //this.Name = myUserName;
            ConnectToServer.Text = "Connect";
            userList = new ArrayList();
            gamesList = new ArrayList();
        }

        private void JoinButton_Click(object sender, EventArgs e)
        {
            //this.Hide();
            //PlayerCreation.
            if (Games.SelectedItem != null)
            {
                // send something to the network that
                // will tell you what game it is

                IGame SelectedGame = null; // = null;//remoteServer.GamesList.ToString();
                foreach (IGame tempGame in remoteServer.GamesList)
                {
                    if (tempGame.GameName == (string)Games.SelectedItem)
                    {
                        SelectedGame = tempGame;
                        break;
                    }
                }
                MessageBox.Show(SelectedGame.GameName + " will be loaded.");
                PlayerCreation playerCreate = new PlayerCreation(remoteServer, myUserName, SelectedGame, connectAddress);
                playerCreate.Show();
            }
            if (Games.SelectedItem == null)
            {
                // do nothing;
            }
        }

        private void ConnectToServer_Click(object sender, EventArgs e)
        {
            string tempServerAddress;
            int i = -1;
            
            tempServerAddress = IPAddress.Text;
            myUserName = PlayerName.Text;

            if (tempServerAddress == string.Empty)
            {
                //tcp://localhost:9887/MULEremoteServer
                connectAddress = tcpServerAddress;
            }
            else
            {
                connectAddress = "tcp://" + tempServerAddress + ":9887/MULEServer";
            }

            //The button says connect, so we start to connect
            if (ConnectToServer.Text == "Connect")
            {
                myUserName = PlayerName.Text;
                if (myUserName.CompareTo(string.Empty) == 0)
                {
                    MessageBox.Show("Please enter a valid user name.");
                    this.Text = "INVALID NAME!";
                }
                //only connect if the user has a nick name
                else
                {
                    PlayerName.Enabled = false;
                    IPAddress.Enabled = false;
                    ChatBox.Enabled = true;
                    tbSend.Enabled = true;
                    SendButton.Enabled = true;
                    btnNewGame.Enabled = true;
                    Players.Enabled = true;
                    Games.Enabled = true;

                    ConnectToServer.Text = "Disconnect";
                    this.Text = myUserName;
                    this.Name = myUserName;

                    StartTCPServer();
                    if (haveConnectedBefore == false)
                    {
                        InitializeRemotingWithServer();
                    }

                    try
                    {
                        i = remoteServer.ConnectToChat(myUserName);
                        //MessageBox.Show(i.ToString(), "returned");
                    }
                    catch (System.Reflection.TargetInvocationException tie)
                    {
                        MessageBox.Show(tie.Message, "tie message");
                        MessageBox.Show(tie.Source, "tie source");
                        MessageBox.Show(tie.ToString(), "tie target");
                    }
                    catch (Exception except)
                    {
                        MessageBox.Show(except.Message);
                    }
                    if (i >= 0) //Server returns index of added player or negative if cant be added
                    {
                        PlayerName.Enabled = false;
                        thread = new Thread(new ThreadStart(PollingService));
                        thread.Start();
                    }
                    else
                    {
                        MessageBox.Show("Pick a better name.");
                        ConnectToServer.Text = "Pick New Name";
                        PlayerName.Enabled = true;
                    }
                }
            }
            //button says disconnect, so we must be connected. we will disconnect.
            else if (ConnectToServer.Text == "Disconnect") 
            {
                remoteServer.DisconnectFromChat(myUserName);
                thread.Abort();
                userList.Clear();
                Players.Items.Clear();
                IPAddress.Enabled = true;
                PlayerName.Enabled = true;
                ChatBox.Enabled = false;
                tbSend.Enabled = false;
                SendButton.Enabled = false;
                btnNewGame.Enabled = false;
                Players.Enabled = false;
                Games.Enabled = false;
                ConnectToServer.Text = "Connect";
            }
            else if (ConnectToServer.Text == "Pick New Name")
            {
                try
                {
                    i = remoteServer.ConnectToChat(myUserName);
                    //MessageBox.Show(i.ToString(), "returned");
                }
                catch (System.Reflection.TargetInvocationException tie)
                {
                    MessageBox.Show(tie.Message, "tie message");
                    MessageBox.Show(tie.Source, "tie source");
                    MessageBox.Show(tie.ToString(), "tie target");
                }
                catch (Exception except)
                {
                    MessageBox.Show(except.Message);
                }
                if (i >= 0) //Server returns index of added player or negative if cant be added
                {
                    ConnectToServer.Text = "Disconnect";
                    thread = new Thread(new ThreadStart(PollingService));
                    thread.Start();
                    PlayerName.Enabled = false;
                }
                else
                {
                    MessageBox.Show("Pick a better name.");
                    ConnectToServer.Text = "Pick New Name";
                    PlayerName.Enabled = true;
                }
            }
        }
        private int StartTCPServer()
        {
            int toReturn = -1;
            //USED TO WORK CODE
            BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
            BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
            serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            IDictionary props = new Hashtable();
            props["port"] = tcpServerPort;
            string s = System.Guid.NewGuid().ToString();
            props["name"] = s;
            props["typeFilterLevel"] = TypeFilterLevel.Full;
            TcpChannel tcpChan = new TcpChannel(
                props, clientProvider, serverProvider);

            ChannelServices.RegisterChannel(tcpChan, false);
            //END USED TO WORK CODE

            //SIMPLE REMOTING CODE
            /*TcpChannel testChan = new TcpChannel();
            ChannelServices.RegisterChannel(testChan, false);*/

            //Type typeofRI = typeof(Chat);
            //iCRoom = (IChatRoom)Activator.GetObject(typeofRI, tcpServerAddress);

            //TcpChannel tcpChan = new TcpChannel();   //tcpServerPort);
            //ChannelServices.RegisterChannel(tcpChan, false);
            //iCRoom = (IChatRoom) Activator.GetObject(typeof(IChatRoom), tcpServerAddress);

            //string temp = iCRoom.AmIConnected();
            //if (temp[0] == 'Y')
            //{
            //    toReturn = 1;
            //}
            //MessageBox.Show(temp);
            return (toReturn + 2);
        }

        private void SendButton_Click(object sender, EventArgs e)
        {
            String toSend = myUserName + ": ";
            toSend += tbSend.Text.Trim() + "\n";
            remoteServer.SendMessage(toSend);
            tbSend.Text = "";
        }

        private void FillUserList()
        {
            int selected = Players.SelectedIndex;
            Players.Items.Clear();
            if (kickMe == true)
            {
                thread.Abort();
                remoteServer.DisconnectFromChat(myUserName);
                userList.Clear();
                Players.Items.Clear();
                IPAddress.Enabled = true;
                PlayerName.Enabled = true;
                ChatBox.Enabled = false;
                tbSend.Enabled = false;
                SendButton.Enabled = false;
                btnNewGame.Enabled = false;
                Players.Enabled = false;
                Games.Enabled = false;
                ConnectToServer.Text = "Connect";
            }
            foreach (string clientName in userList)
            {
                Players.Items.Add(clientName);
            }
            if (Players.Items.Count > selected)
            {
                Players.SelectedIndex = selected;
            }
        }

        private void FillGamesList()
        {

            int selected = Games.SelectedIndex;
            Games.Items.Clear();
            foreach (IGame gameName in gamesList)
            {
                Games.Items.Add(gameName.GameName);
            }
            if (Games.Items.Count > selected)
            {
                Games.SelectedIndex = selected;
            }
            if (Games.Items.Count > 0)
            {
                // turn on join game
                JoinButton.Enabled = true;
            }
            else if (Games.Items.Count < 0)
            {
                JoinButton.Enabled = false;
            }
        }

        private void SetChatBoxText()
        {
            ChatBox.Clear();
            ChatBox.Text = strSessionText;
        }

        private void PollingService()
        {
            ArrayList kickList = new ArrayList();
            while (true)
            {
                Thread.Sleep(1000);
                kickList = remoteServer.kicks;
                userList = remoteServer.ChatClients;
                gamesList = remoteServer.GamesList;
                if (Players.InvokeRequired)
                {
                    try
                    {
                        Players.Invoke(new MethodInvoker(FillUserList), null);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.InnerException.Message);
                    }
                }
                else
                {
                    Console.WriteLine("Polling service is running in the UI thread for some reason...");
                    Console.WriteLine("Players did not require an invoke.");
                }
                strSessionText = remoteServer.ChatSession;
                if (ChatBox.InvokeRequired)
                {
                    try
                    {
                    ChatBox.Invoke(new MethodInvoker(SetChatBoxText), null);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.InnerException.Message);
                    }
                }
                if (Games.InvokeRequired)
                {
                    try
                    {
                        Games.Invoke(new MethodInvoker(FillGamesList), null);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.InnerException.Message);
                    }
                    
                }
                else
                {
                    Console.WriteLine("Polling service is running in the UI thread for some reason...");
                    Console.WriteLine("ChatBox did not require an invoke.");
                }
                if (kickList.Contains((string)myUserName))
                {
                    kickMe = true;
                }
            }
        }

        private void button1_Click(object sender, EventArgs e) //btnNewGame
        {
            NewGame ng = new NewGame(remoteServer, myUserName);

            ng.Show();
            

            /*
            Boolean focus = ng.
            if (focus == false)
            {
                if (Games.Items.Count > 0)
                {
                    // turn on join game
                    JoinButton.Enabled = true;
                }
            }
             * */
        }

        private void IPAddress_TextChanged(object sender, EventArgs e)
        {

        }

        private void Games_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        protected override void OnClosing(CancelEventArgs e)
        {
            MessageBox.Show("Are you sure you wish to exit?");
            if (thread != null)
            {
                thread.Abort();
                remoteServer.DisconnectFromChat(myUserName);
            }
            base.OnClosing(e);
        }
    }
}